home *** CD-ROM | disk | FTP | other *** search
/ The World of Computer Software / The World of Computer Software.iso / inter33c.zip / INTPRINT.C < prev    next >
C/C++ Source or Header  |  1992-10-14  |  40KB  |  1,497 lines

  1. /************************************************************************/
  2. /* INTPRINT.C by Ralf Brown.  Donated to the Public Domain.        */
  3. /* Please do not remove my name from any copies or derivatives.        */
  4. /************************************************************************/
  5. /* Program History:                            */
  6. /*   v1.00  4/23/89  initial public release                */
  7. /*             with 4/30/89 list                    */
  8. /*   v1.10  5/21/89  added -I and -f                    */
  9. /*   v1.11  1/6/90   fixed #endif's for compilers which don't handle    */
  10. /*             labels                        */
  11. /*   v1.20  6/8/90   added -r                        */
  12. /*   v1.30  7/14/90  added -b, tables now stay aligned on odd indents    */
  13. /*   v1.40  10/6/90  added -B based on changes by Naoto Kimura, -w    */
  14. /*   v1.40a 5/6/91   HP LaserJet II support by Russ Herman        */
  15. /*   v1.41  7/9/91   HP PCL support by P.J.Farley III            */
  16. /*   v2.00  9/1/91   modular printer definitions            */
  17. /*             printing multipart interrupt list            */
  18. /*   v2.01  2/9/92   fixed summary entry for non-numeric AX= and AH=    */
  19. /*             smarter page breaks                */
  20. /*   v2.02  2/18/92  bugfix & isxdigit suggested by Aaron West        */
  21. /*   v2.10  3/14/92  updated to handle extra flags in headings        */
  22. /*   v2.11  5/23/92  bugfix pointed out by Joe White            */
  23. /*   v2.20  6/12/92  added -F based on code by Richard Brittain     */
  24. /*             added -H and Panasonic printer def by Lewis Paper    */
  25. /*   v2.21         fixed error in -H/-r interaction            */
  26. /*             updated for new 'Bitmask of' section        */
  27. /************************************************************************/
  28. /* Recompiling:                                */
  29. /*   Turbo C / Borland C++                        */
  30. /*    tcc -mt -lt -Z -p intprint                    */
  31. /************************************************************************/
  32.  
  33. #include <stdio.h>
  34. #include <string.h>
  35. #include <ctype.h>
  36.  
  37. #define VERSION "2.21"
  38.  
  39. #ifdef __TURBOC__
  40. #  define PROTOTYPES
  41. #  include <stdlib.h>
  42.    int _Cdecl isatty(int handle) ;
  43.    void _setenvp(void) {} /* don't need the environment, so don't include it */
  44. #else
  45.  
  46. /* not Turbo C / Borland C, so set configuration #defines */
  47. #if 0  /* set to 1 if compiler supports ANSI-style prototypes, 0 otherwise */
  48. #define PROTOTYPES
  49. #endif
  50. #if 1  /* set to 0 if library contains strnicmp(), 1 otherwise */
  51. #define NEED_STRNICMP
  52. #endif
  53. #if 1  /* set to 0 if library contains isxdigit(), 1 otherwise */
  54. #define NEED_ISXDIGIT
  55. #endif
  56. #if 0  /* set to 0 if library contains strdup(), 1 otherwise */
  57. #define NEED_STRDUP
  58. #endif
  59. #if 1  /* set to 0 if library contains strupr(), 1 otherwise */
  60. #define NEED_STRUPR
  61. #endif
  62. #if 1  /* set to 0 if library contains three-arg itoa(), 1 otherwise */
  63. #define NEED_ITOA
  64. #endif
  65.  
  66. #define _Cdecl
  67.  
  68. #endif /* __TURBOC__ */
  69.  
  70. /***********************************************/
  71.  
  72. #ifndef FALSE
  73. #define FALSE 0
  74. #endif
  75. #ifndef TRUE
  76. #define TRUE !FALSE
  77. #endif
  78.  
  79. #define MAXLINE 81   /* at most 80 chars per line (plus newline) */
  80. #define MAXPAGE 200  /* at most 200 lines per page */
  81.  
  82. #define start_of_entry(s) (strncmp(s,"INT ",4) == 0)
  83.  
  84. /***********************************************/
  85.  
  86. typedef struct _cstr         /* a counted string */
  87.    {
  88.    int len ;             /* the string's length */
  89.    char *str ;             /* the actual contents of the string */
  90.    } cstr ;
  91.  
  92. #define CSTR(s) { sizeof(s)-1, (s) }  /* for defining a counted string literal */
  93. #define cstrlen(s) ((s)->len)     /* how long is the counted string? */
  94. #define cstrchar(s,i) ((s)->str[i])  /* retrieve a character from a counted string */
  95.  
  96. typedef struct _printer_def
  97.    {
  98.    char *name ;            /* for selecting the appropriate printer */
  99.    cstr init1, init2 ;        /* initialization strings */
  100.    cstr marginl, marginc, marginr ; /* margins: duplex even, non-duplex, duplex odd */
  101.    cstr duplex_on ;        /* turn on duplex mode */
  102.    cstr term1, term2 ;        /* cleanup strings */
  103.    cstr bold_on, bold_off ;    /* boldface on/off */
  104.    int indent ;            /* how many extra spaces to indent */
  105.    int lines_per_page ;        /* how many lines to print on each page */
  106.    int page_length ;        /* how many lines on each page */
  107.    int page_width ;        /* how many printable columns per line? */
  108. #ifdef PROTOTYPES
  109.    void (*put_line)(FILE *,int) ;/* function to call to print out divider line */
  110.    void (*set_typeface)(FILE *,char *) ;
  111. #else
  112.    void (*put_line)() ;        /* function to call to print out divider line */
  113.    void (*set_typeface)() ;
  114. #endif /* PROTOTYPES */
  115.    int *flag ;            /* flag to set when using this printer definition */
  116.    } PRINTER_DEF ;
  117.  
  118. struct filter_list
  119.    {
  120.    struct filter_list *next ;
  121.    char *str ;
  122.    } ;
  123.  
  124. typedef struct _header
  125.    {
  126.    int part ;
  127.    int first_on_page ; /* TRUE if a new entry starts at the top of the page */
  128.    char desc[24] ;
  129.    } HEADER ;
  130.  
  131. /***********************************************/
  132.  
  133. #ifdef PROTOTYPES
  134. void usage(void) ;
  135. void fatal(char *msg) ;
  136. void get_raw_line(char *buf,int size) ;
  137. int unwanted_section(char *buf) ;
  138. void get_line(char *buf,int size) ;
  139. void indent_line(FILE *fp) ;
  140. void indent_to(int where,FILE *fp) ;
  141. void put_line(FILE *fp, int len) ;
  142. void HPPCL_put_line(FILE *fp, int len) ;
  143. void HPPCL_set_typeface(FILE *fp,char *typeface) ;
  144. void fputcstr(cstr *s, FILE *fp) ;
  145. int divider_line(char *line) ;
  146. int section_start(char *line) ;
  147. int start_of_table(char *line) ;
  148. void output_line(char *line,FILE *fp) ;
  149. void fill_buffer(int lines, int lines_per_page) ;
  150. int find_page_break(int lines) ;
  151. void summarize(FILE *summary, int line, int pages_printed) ;
  152. void start_format(char *line) ;
  153. struct filter_list *add_filter_info(struct filter_list *list,char *str) ;
  154. void build_filter_lists(char *file) ;
  155. void print_line(char *line) ;
  156. void make_description(char *desc,int line) ;
  157. char *determine_heading(int last) ;
  158. void print_buffer(int last, int lines_per_page, int total_lines, int use_FF) ;
  159. void select_printer(char *name) ;
  160. void display_printers(void) ;
  161. int _Cdecl main(int argc, char **argv) ;
  162. #else
  163. void put_line() ;
  164. void HPPCL_put_line() ;
  165. #endif /* PROTOTYPES */
  166.  
  167. /***********************************************/
  168.  
  169. FILE *infile, *outfile ;
  170. char *input_file ;
  171.  
  172. char buffer[MAXPAGE][MAXLINE] ;
  173. char num[6] ;
  174. char summary_line[2*MAXLINE] ;
  175.  
  176. int pages_printed = 0 ;
  177. int page_width = 0 ;        /* page width in characters, 0 = use prtdef */
  178. int indent = 0 ;        /* number of blanks to add at start of each line */
  179. int widow_length = 10 ;        /* number of lines to scan for good place to break */
  180. int page_numbers = FALSE ;    /* add page numbers to bottom of page? */
  181. int multi_file = FALSE ;    /* printing multipart interrupt list? */
  182. int out_of_files = FALSE ;    /* hit end of last file for multipart printing? */
  183. int do_summary = FALSE ;    /* create a one-line-per-call summary? */
  184. int do_formats = FALSE ;    /* create a separate file with data structures? */
  185. int do_filter = FALSE ;        /* using a filtering file? */
  186. int do_headers = FALSE ;    /* add page headings? */
  187. int IBM_chars = FALSE ;        /* printer can handle IBM graphics characters */
  188. int boldface = FALSE ;        /* boldface titles and Return:/Notes: ? */
  189. int printer_bold = FALSE ;    /* boldface using printer control sequences? */
  190. int echo_format = FALSE ;
  191. int duplex = FALSE ;
  192. int HPPCL_mode = FALSE ;
  193. FILE *summary ;
  194. FILE *formats ;
  195. PRINTER_DEF *printer = NULL ;
  196.  
  197. int first_page = 0 ;
  198. int last_page = 9999 ;
  199.  
  200. struct filter_list *includes = NULL ;
  201. struct filter_list *excludes = NULL ;
  202.  
  203. HEADER header_first = { 0, FALSE, "" } ;
  204. HEADER header_last = { 0, FALSE, "" } ;
  205.  
  206. /***********************************************/
  207.  
  208. PRINTER_DEF printers[] =
  209.    {
  210.      { "default",
  211.        CSTR(""), CSTR(""),
  212.        CSTR(""), CSTR(""), CSTR(""),
  213.        CSTR(""),
  214.        CSTR(""), CSTR(""),
  215.        CSTR(""), CSTR(""),
  216.        -1,
  217.        60,
  218.        0,
  219.        79,
  220.        put_line,
  221.        NULL,
  222.        NULL,
  223.      },
  224.      { "Epson FX80, 12 cpi",
  225.        CSTR("\033M"), CSTR(""),
  226.        CSTR("\033l\004"), CSTR("\033l\007"), CSTR("\033l\014"),
  227.        CSTR(""),
  228.        CSTR("\033P"), CSTR("\033l\000"),
  229.        CSTR("\033E"), CSTR("\033F"),
  230.        0,
  231.        60,
  232.        0,
  233.        87,    /* 96 - left margin - 1 right margin */
  234.        put_line,
  235.        NULL,
  236.        NULL,
  237.      },
  238.      { "Panasonic KX-P1124i / 10 cpi Epson",
  239.        CSTR(""), CSTR(""),
  240.        CSTR(""), CSTR(""), CSTR(""),
  241.        CSTR(""),
  242.        CSTR(""), CSTR(""),
  243.        CSTR("\033E"), CSTR("\033F"),
  244.        -1,
  245.        60,
  246.        0,
  247.        79,
  248.        put_line,
  249.        NULL,
  250.        NULL,
  251.      },
  252.      { "HP PCL",
  253.        CSTR("\033(8U"), CSTR(""),
  254.        CSTR("\033&a4c4L"), CSTR("\033&a8c8L"), CSTR("\033&a12c12L"),
  255.        CSTR("\033&l1S"),
  256.        CSTR("\033E"), CSTR(""),
  257.        CSTR("\033(s3B"), CSTR("\033(s0B"),
  258.        0,
  259.        69,
  260.        0,
  261.        87,    /* 96 - left margin - 1 right margin */
  262.        HPPCL_put_line,
  263.        HPPCL_set_typeface,
  264.        &HPPCL_mode,
  265.      },
  266. #define HPPCL_FONT_ON_A "\033(s0p12h10v0s0b"
  267. /* HP PCL4/5 Font select: Roman-8;Upright12Pitch10PointMediumWeight */
  268. #define HPPCL_FONT_ON_B "T\033&l6.8571C"
  269. /* HP PCL4/5 Font select: End typeface select;VMI=7LPI: (48/7)-48th's inches*/
  270. #define HPPCL_IBM_LN_A    "\033&f0S\033*p-15Y\033*c"
  271. /* HP PCL4/5 IBM Line:    Push Pos;Up 15/720";Hor.Rule ???/300ths" long */
  272. #define HPPCL_IBM_LN_B    "a3b0P\033&f1S"
  273. /* HP PCL4/5 IBM Line:     3/300ths" high,Print rule;Pop Position */
  274.      { "LaserJet II",
  275.        CSTR("\033(10U"),CSTR(""),
  276.        CSTR("\033&a4c4L"), CSTR("\033&a8c8L"), CSTR("\033&a12c12L"),
  277.        CSTR(""),
  278.        CSTR("\033E"),CSTR(""),
  279.        CSTR("\033(s3B"),CSTR("\033(s0B"),
  280.        0,
  281.        54,
  282.        60,
  283.        79,
  284.        put_line,
  285.        NULL,
  286.        &IBM_chars,
  287.      },
  288.    } ;
  289. #define NUM_PRINTERS (sizeof(printers)/sizeof(printers[0]))
  290.  
  291. /***********************************************/
  292.  
  293. #ifdef NEED_STRNICMP
  294. #ifdef PROTOTYPES
  295. int strnicmp(char *s1,char *s2,int len)
  296. #else
  297. int strnicmp(s1,s2,len)
  298. char *s1,*s2 ;
  299. unsigned int len ;
  300. #endif PROTOTYPES
  301. {
  302.    char c1, c2 ;
  303.  
  304.    while (*s1 && *s2 && len > 0)
  305.       {
  306.       len-- ;
  307.       c1 = (islower(*s1) ? toupper(*s1) : *s1) ;
  308.       c2 = (islower(*s2) ? toupper(*s2) : *s2) ;
  309.       if (c1 != c2 || len == 0)     /* mismatch or substrings exhausted? */
  310.      return (c1 - c2) ;
  311.       s1++ ;
  312.       s2++ ;
  313.       }
  314.    return 0 ;  /* strings match exactly on first 'len' characters */
  315. }
  316. #endif /* NEED_STRNICMP */
  317.  
  318. #ifdef NEED_STRUPR
  319. #ifdef PROTOTYPES
  320. char *strupr(char *s)
  321. #else
  322. char *strupr(s)
  323. char *s ;
  324. #endif /* PROTOTYPES */
  325. {
  326.    char *orig_s = s ;
  327.    char c ;
  328.    
  329.    if (s)
  330.       while (*s)
  331.      {
  332.      c = *s ;      
  333.      *s++ = (islower(c) ? toupper(c) : c) ;
  334.      }
  335.    return orig_s ;
  336. }
  337. #endif /* NEED_STRUPR */
  338.  
  339. #ifdef NEED_STRDUP
  340. #ifdef PROTOTYPES
  341. char *strdup(char *s)
  342. #else
  343. char *strdup(s)
  344. char *s ;
  345. #endif /* PROTOTYPES */
  346. {
  347.    char *copy ;
  348.       
  349.    if (s)
  350.       copy = (char *)malloc(strlen(s)+1) ;
  351.    else
  352.       copy = NULL ;   
  353.    if (copy)
  354.       strcpy(copy,s) ;
  355.    return copy ;
  356. }
  357. #endif /* NEED_STRDUP */
  358.  
  359. #ifdef NEED_ISXDIGIT
  360. #ifdef PROTOTYPES
  361. int isxdigit(int c)
  362. #else
  363. int isxdigit(c)
  364. int c ;
  365. #endif /* PROTOTYPES */
  366. {
  367.    return isdigit(c) || (strchr("ABCDEFabcdef",c) != NULL) ;
  368. }
  369. #endif /* NEED_ISXDIGIT */
  370.  
  371. #ifdef NEED_ITOA
  372. #ifdef PROTOTYPES
  373. char *itoa(int num,char *buf,int radix)
  374. #else
  375. char *itoa(num,buf,radix)   /* not everybody has the same itoa() as TurboC */
  376. int num ;            /* minimal implementation */
  377. char *buf ;
  378. int radix ;
  379. #endif /* PROTOTYPES */
  380. {
  381.    int count = 0 ;
  382.    int i ; 
  383.    char tmp ;
  384.  
  385.    do {
  386.       buf[count++] = '0' + num % radix ;
  387.       num = num / radix ;
  388.    } while (num) ;
  389.    buf[count] = '\0' ;
  390.    if (count > 1)
  391.       for (i = 0 ; i < count / 2 ; i++)
  392.      {
  393.      tmp = buf[i] ;
  394.      buf[i] = buf[count-i-1] ;
  395.      buf[count-i-1] = tmp ;
  396.      }
  397.    return buf ;
  398. }
  399. #endif /* NEED_ITOA */
  400.  
  401. /***********************************************/
  402.  
  403. void usage()
  404. {
  405.    fputs("Usage: intprint [options] intlist [>|>>]output\n",stderr) ;
  406.    fputs("Options:\n",stderr) ;
  407.    fputs("\t-b\tboldface title lines and section headings\n",stderr) ;
  408.    fputs("\t-B\tboldface using printer control codes instead of overprinting\n",stderr) ;
  409.    fputs("\t-d\t(duplex) print even/odd pages with different indents\n",stderr) ;
  410.    fputs("\t-e\tassume 'elite' mode (96 chars per line) for default printer\n",stderr) ;
  411.    fputs("\t-ffile\twrite all data structure formats to 'file'\n",stderr) ;
  412.    fputs("\t-Ffile\tprint only entries matching filtering info in 'file'\n",stderr);
  413.    fputs("\t-H\tadd page headers showing interrupt call(s) on page\n",stderr) ;
  414.    fputs("\t-iN\tindent output N spaces (overridden by some printers)\n",stderr) ;
  415.    fputs("\t-I\tprinter supports IBM graphics characters\n",stderr) ;
  416.    fputs("\t-lN\tprint N lines per page (default depends on printer)\n",stderr) ;
  417.    fputs("\t-LN\tassume N lines on a page, use linefeeds if > #lines printed\n",stderr) ;
  418.    fputs("\t-m\tlist is in multiple parts starting with the named file\n",stderr) ;
  419.    fputs("\t-nN\tassume N pages have been printed from previous parts\n",stderr) ;
  420.    fputs("\t-p\tadd page numbers\n",stderr) ;
  421.    fputs("\t-Pname\tassume printer 'name' (-P? lists supported printers)\n",stderr) ;
  422.    fputs("\t-rN:M\tprint only pages N through M\n",stderr) ;
  423.    fputs("\t-sfile\twrite a one-line-per-function summary to 'file'\n",stderr) ;
  424.    fputs("\t-tN\tselect typeface N for the chosen printer\n",stderr) ;
  425.    fputs("\t-wN\tscan N lines from bottom of page for good place to break\n",stderr) ;
  426.    exit(1) ;
  427. }
  428.  
  429. /***********************************************/
  430.  
  431. void fatal(msg)
  432. char *msg ;
  433. {
  434.    fputs(msg,stderr) ;
  435.    fputs("\n",stderr) ;
  436.    exit(1) ;
  437. }
  438.  
  439. /***********************************************/
  440.  
  441. void indent_line(fp)
  442. FILE *fp ;
  443. {
  444.    int ind = indent ;
  445.  
  446.    while (ind >= 8)
  447.       {
  448.       fputc('\t',fp) ;
  449.       ind -= 8 ;
  450.       }
  451.    while (ind-- > 0)
  452.       fputc(' ', fp) ;
  453. }
  454.  
  455. /***********************************************/
  456.  
  457. void indent_to(where,fp)
  458. int where ;
  459. FILE *fp ;
  460. {
  461.    indent_line(fp) ;
  462.    while (where-- > 0)
  463.       fputc(' ', fp) ;
  464. }
  465.  
  466. /***********************************************/
  467.  
  468. void put_line(fp,len)
  469. FILE *fp ;
  470. int len ;
  471. {
  472.    int i ;
  473.  
  474.    if (IBM_chars)
  475.       for (i = 0 ; i < len ; i++)
  476.      fputc(196,fp) ;  /* single horizontal line */
  477.    else
  478.       for (i = 0 ; i < len ; i++)
  479.      fputc('-',fp) ;
  480. }
  481.  
  482. /***********************************************/
  483.  
  484. void HPPCL_put_line(fp,len)
  485. FILE *fp ;
  486. int len ;
  487. {
  488.    fputs(HPPCL_IBM_LN_A,fp) ;
  489.    itoa((len * 25), num, 10) ;
  490.    fputs(num,fp) ;
  491.    fputs(HPPCL_IBM_LN_B,fp) ;
  492. }
  493.  
  494. /***********************************************/
  495.  
  496. void HPPCL_set_typeface(fp,typeface)
  497. FILE *fp ;
  498. char *typeface ;
  499. {
  500.    fputs(HPPCL_FONT_ON_A,fp) ;
  501.    if (typeface)
  502.       fputs(typeface,fp) ;
  503.    else
  504.       fputs("8",fp) ;
  505.    fputs(HPPCL_FONT_ON_B,fp) ;
  506. }
  507.  
  508. /***********************************************/
  509.  
  510. void fputcstr(s,fp)        /* output the counted string to the given file */
  511. FILE *fp ;
  512. cstr *s ;
  513. {
  514.    int i ;
  515.  
  516.    for (i = 0 ; i < cstrlen(s) ; i++)
  517.       fputc(cstrchar(s,i),fp) ;
  518. }
  519.  
  520. /***********************************************/
  521.  
  522. int divider_line(line)
  523. char *line ;
  524. {
  525.    return strncmp(line,"--------",8) == 0 ;
  526. }
  527.  
  528. /***********************************************/
  529.  
  530. int section_start(line)
  531. char *line ;
  532. {
  533.    return (strncmp(line,"Return:",7) == 0 ||
  534.        strncmp(line,"Desc:",5) == 0 ||
  535.        strncmp(line,"Note:",5) == 0 ||
  536.        strncmp(line,"Notes:",6) == 0 ||
  537.        strncmp(line,"SeeAlso:",8) == 0 ||
  538.        strncmp(line,"BUG:",4) == 0 ||
  539.            strncmp(line,"BUGS:",5) == 0 ||
  540.            strncmp(line,"Program:",8) == 0
  541.       ) ;
  542. }
  543.  
  544. /***********************************************/
  545.  
  546. int start_of_table(line)
  547. char *line ;
  548. {
  549.    return (strncmp(line,"Format of ",10) == 0 ||
  550.            strncmp(line,"Values ",7) == 0 ||
  551.            strncmp(line,"Call ",5) == 0 ||
  552.            strncmp(line,"Bitmask of ",11) == 0
  553.           ) ;
  554. }
  555.    
  556. /***********************************************/
  557.  
  558. void output_line(line,fp)
  559. char *line ;
  560. FILE *fp ;
  561. {
  562.    int pos = 0 ;
  563.    char bold[10] ;
  564.  
  565.    if (boldface)
  566.       {
  567.       if (start_of_entry(line) || start_of_table(line))
  568.      {
  569.      indent_line(fp) ;
  570.      if (printer_bold)
  571.         {
  572.         fputcstr(&printer->bold_on,fp) ;
  573.         fputs(line,fp) ;
  574.         fputcstr(&printer->bold_off,fp) ;
  575.         line = NULL ;
  576.         }
  577.      else
  578.         {
  579.         fputs(line,fp) ;
  580.         fputc('\r',fp) ;
  581.         }
  582.      }
  583.       else if (section_start(line))
  584.      {
  585.      strncpy(bold,line,sizeof bold) ;
  586.      *strchr(bold,':') = '\0' ;
  587.      indent_line(fp) ;
  588.      if (printer_bold)
  589.         {
  590.         fputcstr(&printer->bold_on,fp) ;
  591.         fputs(bold,fp) ;
  592.         fputcstr(&printer->bold_off,fp) ;
  593.         pos = strlen(bold) ;     /* we're no longer at the left edge of the */
  594.         line += pos ;         /* line, so figure out where we are */
  595.         }
  596.      else
  597.         {
  598.         fputs(bold,fp) ;
  599.         fputc('\r',fp) ;
  600.         }
  601.      }
  602.       } /* boldface */
  603.    if (line && *line)
  604.       {
  605.       if (pos == 0)        /* are we currently at the left edge of the line? */
  606.      indent_line(fp) ;  /* if yes, indent the desired amount */
  607.       if (indent % 8)
  608.      {
  609.      while (*line)
  610.         {
  611.         if (*line == '\t')
  612.            do {
  613.           fputc(' ',fp) ;
  614.           } while (++pos % 8) ;
  615.         else
  616.            {
  617.            fputc(*line,fp) ;
  618.            pos++ ;
  619.            }
  620.         line++ ;
  621.         }
  622.      }
  623.       else
  624.      fputs(line,fp) ;
  625.       }
  626.    fputc('\n',fp) ;
  627. }
  628.  
  629. /***********************************************/
  630.  
  631. void get_raw_line(buf,size)
  632. char *buf ;
  633. int size ;
  634. {
  635.    int last ;
  636.  
  637.    buf[0] = '\0' ;
  638.    if (out_of_files)
  639.       return ;
  640.    fgets(buf,size,infile) ;
  641.    if ((feof(infile) || buf[0] == '\0'))
  642.       if (multi_file)
  643.      {
  644.      FILE *tempfile ;
  645.  
  646.      last = strlen(input_file) - 1 ;
  647.      input_file[last]++ ;
  648.      if ((tempfile = fopen(input_file,"r")) != NULL)
  649.         {
  650.         fclose(infile) ;
  651.         infile = tempfile ;
  652.         fgets(buf,size,infile) ;
  653.         }
  654.      else
  655.         {
  656.         out_of_files = TRUE ;
  657.         return ;
  658.         }
  659.      }
  660.       else
  661.      out_of_files = TRUE ;
  662.    last = strlen(buf) - 1 ;
  663.    if (last < 0)
  664.       last = 0 ;
  665.    if (buf[last] == '\n')
  666.       buf[last] = '\0' ;  /* strip the newline */
  667. }
  668.  
  669. /***********************************************/
  670.  
  671. int unwanted_section(buf)
  672. char *buf ;
  673. {
  674.    int unwanted = FALSE ;
  675.    int found ;
  676.    char str[MAXLINE] ;
  677.    struct filter_list *p ;
  678.    
  679.    if (start_of_entry(buf)) /* is it an interrupt entry? */
  680.       {
  681.       strncpy(str,buf,sizeof str) ;
  682.       str[sizeof str - 1] = '\0' ;
  683.       (void) strupr(str) ;
  684.       /* set 'unwanted' to TRUE if *any* exclude string matches */
  685.       for (p = excludes ; p ; p = p->next)
  686.      {
  687.      if (p->str && strstr(str, p->str) != NULL)
  688.         {
  689.         unwanted = TRUE ;
  690.         break ;
  691.         }
  692.      }
  693.       /* if still wanted, set to TRUE if *no* include string matches */
  694.       if (!unwanted)
  695.      {
  696.      found = FALSE ;
  697.      for (p = includes ; p ; p = p->next)
  698.         {
  699.         if (p->str && strstr(str, p->str) != NULL)
  700.            {
  701.            found = TRUE ;
  702.            break ; 
  703.            }
  704.         }
  705.      if (!found)
  706.         unwanted = TRUE ;
  707.      }
  708.       }
  709.    return unwanted ;
  710. }
  711.  
  712. /***********************************************/
  713.  
  714. void get_line(buf,size)
  715. char *buf ;
  716. int size ;
  717. {
  718.    static char next_line[MAXLINE] ;
  719.    static int readahead = FALSE ;
  720.  
  721.    /* get the next line from the file, skipping unwanted entries */
  722.    if (readahead)
  723.       {
  724.       strncpy(buf,next_line,size) ;
  725.       buf[size-1] = '\0' ;
  726.       readahead = FALSE ;
  727.       }
  728.    else
  729.       {
  730.       get_raw_line(buf,size) ;
  731.       strncpy(next_line,buf,sizeof next_line);
  732.       next_line[sizeof next_line - 1] = '\0' ;
  733.       /* if we read a divider line, we have to look ahead */
  734.       while (do_filter && next_line[0] && divider_line(next_line))
  735.      {
  736.      strncpy(buf,next_line,size) ; /* we may be returning the divider */
  737.      buf[size-1] = '\0' ;
  738.      get_raw_line(next_line,sizeof next_line) ;
  739.      if (unwanted_section(next_line))
  740.         {
  741.         while (!divider_line(next_line))
  742.            get_raw_line(next_line,sizeof next_line) ;
  743.         }
  744.      else /* section is wanted, so return divider and then next line */
  745.         readahead = TRUE ;
  746.      }
  747.       }
  748. }
  749.  
  750. /***********************************************/
  751.  
  752. void fill_buffer(lines,lines_per_page)
  753. int lines, lines_per_page ;
  754. {
  755.    int i ;
  756.  
  757.    if (lines)
  758.       for (i = lines ; i < lines_per_page ; i++)
  759.      strcpy(buffer[i-lines], buffer[i]) ;
  760.    else
  761.       lines = lines_per_page ;
  762.    for (i = lines_per_page - lines ; i < lines_per_page ; i++)
  763.       get_line(buffer[i], sizeof(buffer[i])) ;
  764. }
  765.  
  766. /***********************************************/
  767.  
  768. int find_page_break(lines)
  769. int lines ;
  770. {
  771.    int i ;
  772.  
  773.    for (i = 0 ; i < widow_length ; i++)
  774.       {
  775.       if (strcmp(buffer[lines-i-1],"\n") == 0 ||
  776.       strlen(buffer[lines-i-1]) == 0 ||
  777.       divider_line(buffer[lines-i-1]) ||
  778.       section_start(buffer[lines-i]))
  779.      return lines - i ;
  780.       }
  781.    return lines ;
  782. }
  783.  
  784. /***********************************************/
  785.  
  786. void summarize(summary, line, pages_printed)
  787. FILE *summary ;
  788. int line, pages_printed ;
  789. {
  790.    char *s ;
  791.    int i ;
  792.    int max_descrip ;
  793.    int len ;
  794.  
  795.    s = buffer[line] ;
  796.    if (start_of_entry(s))
  797.       {
  798.       summary_line[3] = summary_line[0] = ' ' ;
  799.       summary_line[1] = s[4] ;     /* output interrupt number */
  800.       summary_line[2] = s[5] ;
  801.       summary_line[4] = '\0' ;
  802.       len = 4 ;
  803.       s = buffer[line+1] ;
  804.       while (*s && isspace(*s))
  805.      s++ ;
  806.       if (*s == 'A')
  807.      {
  808.      if (s[1] == 'X')
  809.         i = 4 ;
  810.      else
  811.         i = (s[1] == 'H') ? 2 : 0 ;
  812.      }
  813.       else
  814.      i = 0 ;
  815.       if (i)
  816.      {
  817.      while (*s && *s != '=')
  818.         s++ ;
  819.      s++ ;    /* skip the equal sign */
  820.      while (*s && isspace(*s))
  821.         s++ ;
  822.      if (isxdigit(*s) && isxdigit(s[1]))
  823.         {
  824.         summary_line[len++] = *s++ ;
  825.         summary_line[len++] = *s++ ;
  826.         summary_line[len++] = ' ' ;
  827.         if (i == 4)
  828.            {
  829.            summary_line[len++] = *s++ ;
  830.            summary_line[len++] = *s ;
  831.            }
  832.         else
  833.            {
  834.            summary_line[len++] = '-' ;
  835.            summary_line[len++] = '-' ;
  836.            }
  837.         summary_line[len++] = ' ' ;
  838.         }
  839.      else
  840.         {
  841.         /* wasn't legal digit, so no numbers */
  842.         strcpy(summary_line+len,"-- -- ") ;
  843.         len += 6 ;
  844.         }
  845.      }
  846.       else
  847.      {
  848.      strcpy(summary_line+len,"-- -- ") ;
  849.      len += 6 ;
  850.      }
  851.       if (page_numbers)
  852.      {
  853.      itoa(pages_printed,num,10) ;
  854.      for (i = strlen(num) ; i < 3 ; i++)
  855.         summary_line[len++] = ' ' ;
  856.      strcpy(summary_line+len,num) ;
  857.      len += strlen(num) ;
  858.      summary_line[len++] = ' ' ;
  859.      }
  860.       s = buffer[line] + 7 ;    /* find function description */
  861.       if (*s && *s != '-')    /* does the heading contain flags? */
  862.      {
  863.      while (*s && !isspace(*s))
  864.         summary_line[len++] = *s++ ;
  865.      summary_line[len++] = '>' ;
  866.      summary_line[len++] = ' ' ;
  867.      while (*s && *s != '-')
  868.         s++ ;
  869.      }
  870.       while (*s && !isspace(*s))
  871.      s++ ;
  872.       while (*s && isspace(*s))
  873.      s++ ;
  874.       max_descrip = (page_width > sizeof(summary_line)-1) ? 
  875.                    sizeof(summary_line)-1 : page_width ;
  876.       while (len < max_descrip && *s)
  877.      summary_line[len++] = *s++ ;
  878.       summary_line[len] = '\0' ;
  879.       if (do_summary && summary)
  880.      output_line(summary_line,summary) ;
  881.       }
  882. }
  883.  
  884. /***********************************************/
  885.  
  886. void start_format(line)
  887. char *line ;
  888. {
  889.    indent_line(formats) ;
  890.    (*printer->put_line)(formats,79) ;
  891.    fputc('\n',formats) ;
  892.    indent_line(formats) ;
  893.    fputs(summary_line,formats) ;
  894.    fputc('\n',formats) ;
  895.    indent_line(formats) ;
  896.    fputc('\t',formats) ;
  897.    fputs(line+10,formats) ;
  898.    fputc('\n',formats) ;
  899.    echo_format = TRUE ;
  900. }
  901.  
  902. /***********************************************/
  903.  
  904. void print_line(line)
  905. char *line ;
  906. {
  907.    if (*line)
  908.       {
  909.       if (divider_line(line))
  910.      {
  911.      indent_line(outfile) ;
  912.      (*printer->put_line)(outfile,79) ;
  913.      fputc('\n', outfile) ;
  914.      echo_format = FALSE ;
  915.      }
  916.       else
  917.      {
  918.      output_line(line, outfile) ;
  919.      if (echo_format)
  920.         output_line(line,formats) ;
  921.      }
  922.       }
  923.    else
  924.       {
  925.       fputc('\n', outfile) ;
  926.       echo_format = FALSE ;
  927.       }
  928. }
  929.  
  930. /***********************************************/
  931.  
  932. void make_description(desc,line)
  933. char *desc ;
  934. int line ;
  935. {
  936.    summarize(NULL,line,0) ;
  937.    memcpy(desc,"INT ", 4) ;
  938.    desc += 4 ;
  939.    *desc++ = summary_line[1] ;
  940.    *desc++ = summary_line[2] ;
  941.    if (summary_line[4] != '-')
  942.       {
  943.       memcpy(desc,", AH=", 5) ;
  944.       desc += 5 ;
  945.       *desc++ = summary_line[4] ;
  946.       *desc++ = summary_line[5] ;
  947.       if (summary_line[7] != '-')
  948.      {
  949.      memcpy(desc,", AL=", 5) ;
  950.      desc += 5 ;
  951.      *desc++ = summary_line[7] ;
  952.      *desc++ = summary_line[8] ;
  953.      }
  954.       }   
  955.    *desc = '\0' ;
  956. }
  957.  
  958. /***********************************************/
  959.  
  960. char *determine_heading(last)
  961. int last ;
  962. {
  963.    int i ;
  964.    char *heading ;
  965.    char num[10] ;
  966.    
  967.    if (start_of_entry(buffer[0]))
  968.       {
  969.       make_description(header_first.desc,0) ;
  970.       header_first.part = 1 ;
  971.       header_first.first_on_page = TRUE ;
  972.       }
  973.    else if (header_last.part == 0)  /* very first entry? */
  974.       {
  975.       for (i = 0 ; i < last ; i++)
  976.      if (start_of_entry(buffer[i]))
  977.         {
  978.         make_description(header_first.desc,i) ;
  979.         header_first.part = 1 ;
  980.         header_first.first_on_page = TRUE ;
  981.         break ;
  982.         }
  983.       }
  984.    else
  985.       {
  986.       strcpy(header_first.desc,header_last.desc) ;
  987.       header_first.part = header_last.part + 1 ;
  988.       header_first.first_on_page = FALSE ;
  989.       }
  990.    /* assume entry spans entire page */
  991.    strcpy(header_last.desc,header_first.desc) ;
  992.    header_last.part = header_first.part ;
  993.    header_last.first_on_page = header_first.first_on_page ;
  994.    /* find last entry on page */
  995.    if (header_first.part > 0)
  996.       {
  997.       if ((heading = calloc(1,MAXLINE)) == NULL)
  998.          return NULL ;
  999.       for (i = last-1 ; i > 0 ; i--)
  1000.      if (start_of_entry(buffer[i]))
  1001.         {
  1002.         make_description(header_last.desc,i) ;
  1003.         header_last.part = 1 ;
  1004.         header_last.first_on_page = FALSE ;
  1005.         break ;
  1006.         }
  1007.       strcpy(heading,header_first.desc) ;
  1008.       if (header_first.part > 1)
  1009.      {
  1010.      strcat(heading," (Part ") ;
  1011.      itoa(header_first.part,num,10) ;
  1012.      strcat(heading,num) ;
  1013.      strcat(heading,")") ;
  1014.      }
  1015.       if (strcmp(header_first.desc,header_last.desc) != 0 ||
  1016.       header_first.part != header_last.part)
  1017.      {
  1018.      strcat(heading," to ") ;
  1019.      strcat(heading,header_last.desc) ;
  1020.      if (header_last.part > 1)
  1021.         {
  1022.         strcat(heading," (Part ") ;
  1023.         itoa(header_last.part,num,10) ;
  1024.         strcat(heading,num) ;
  1025.         strcat(heading,")") ;
  1026.         }
  1027.      }
  1028.       return heading ; 
  1029.       }
  1030.    else /* no headings yet */
  1031.       return NULL ;
  1032. }
  1033.  
  1034. /***********************************************/
  1035.  
  1036. void print_buffer(last,lines_per_page,total_lines,use_FF)
  1037. int last, lines_per_page, total_lines ;
  1038. int use_FF ;
  1039. {
  1040.    int i ;
  1041.  
  1042.    pages_printed++ ;
  1043.    if (do_headers)
  1044.       {
  1045.       char *heading ;
  1046.       
  1047.       if ((heading = determine_heading(last)) != NULL)
  1048.      {
  1049.      if (pages_printed >= first_page && pages_printed <= last_page)
  1050.         {
  1051.         indent_to(40-strlen(heading)/2,outfile) ;
  1052.         if (boldface)
  1053.            {
  1054.            if (printer_bold)
  1055.           {
  1056.           fputcstr(&printer->bold_on,outfile) ;
  1057.           fputs(heading,outfile) ;
  1058.           fputcstr(&printer->bold_off,outfile) ;
  1059.           }
  1060.            else
  1061.           {
  1062.           fputs(heading,outfile) ;
  1063.           fputc('\r',outfile) ;
  1064.           indent_to(40-strlen(heading)/2,outfile) ;
  1065.           fputs(heading,outfile) ;
  1066.           }
  1067.            }
  1068.         else
  1069.            fputs(heading,outfile) ;
  1070.         }
  1071.      free(heading) ;
  1072.      }
  1073.       fputs("\n\n",outfile) ;
  1074.       }
  1075.    for (i = 0 ; i < last ; i++)
  1076.       {
  1077.       if (pages_printed >= first_page && pages_printed <= last_page)
  1078.      print_line(buffer[i]) ;
  1079.       if (do_summary || do_formats)  /* need summary lines if doing formats */
  1080.      summarize(summary,i,pages_printed) ;
  1081.       if (do_formats && strncmp(buffer[i],"Format of ",10) == 0)
  1082.      start_format(buffer[i]) ;
  1083.       }
  1084.    if (pages_printed >= first_page && pages_printed <= last_page)
  1085.       {
  1086.       if (page_numbers)
  1087.      {
  1088.      for (i = last ; i < lines_per_page - 1 ; i++)
  1089.         fputc('\n', outfile) ;
  1090.      indent_to(38,outfile) ;
  1091.      fputs("- ", outfile) ;
  1092.      itoa(pages_printed, num, 10) ;
  1093.      fputs(num, outfile) ;
  1094.      fputs(" -\n", outfile) ;
  1095.      }
  1096.       if (use_FF)
  1097.      fputc('\f', outfile) ;
  1098.       else
  1099.      for (i = page_numbers?lines_per_page:last ; i<total_lines ; i++)
  1100.         fputc('\n', outfile) ;
  1101.       if (duplex)
  1102.      {
  1103.      if ((pages_printed % 2) == 1)    /* next page even or odd? */
  1104.         fputcstr(&printer->marginl, outfile) ;    /* even page */
  1105.      else
  1106.         fputcstr(&printer->marginr, outfile) ;    /* odd page */
  1107.      }
  1108.       }
  1109. }
  1110.  
  1111. /***********************************************/
  1112.  
  1113. void display_printers()
  1114. {
  1115.    int i ;
  1116.    
  1117.    fputs("Valid printer names are:\n",stderr) ;
  1118.    for (i = 0 ; i < NUM_PRINTERS ; i++)
  1119.       {
  1120.       fputc('\t',stderr) ;
  1121.       fputs(printers[i].name,stderr) ;
  1122.       fputc('\n',stderr) ;
  1123.       }
  1124.    fputs("When entering the printer name, use either a dash or an underscore\n",stderr) ;
  1125.    fputs("in place of blanks.  Case is ignored, and the name may be abbreviated\n",stderr) ;
  1126.    fputs("to the shortest unique prefix.\n",stderr) ;
  1127.    exit(1) ;
  1128. }
  1129.  
  1130. /***********************************************/
  1131.  
  1132. void select_printer(name)
  1133. char *name ;
  1134. {
  1135.    int i, len, prt = -1 ;
  1136.    
  1137.    len = strlen(name) ;
  1138.    for (i = 0 ; i < len ; i++)        /* convert dashes and underscores to blanks */
  1139.       if (name[i] == '-' || name[i] == '_')
  1140.      name[i] = ' ' ;
  1141.    for (i = 0 ; i < NUM_PRINTERS ; i++)
  1142.       if (strnicmp(name,printers[i].name,strlen(name)) == 0)
  1143.      if (prt == -1)
  1144.         prt = i ;
  1145.      else
  1146.         fatal("Ambiguous printer name!  Use -P? to list printers.") ;
  1147.    if (prt == -1)
  1148.       fatal("Unknown printer name!  Use -P? to list printers.") ;
  1149.    else
  1150.       printer = &printers[prt] ;
  1151. }
  1152.  
  1153. /***********************************************/
  1154.  
  1155. struct filter_list *add_filter_info(list,str)
  1156. struct filter_list *list ;
  1157. char *str ;
  1158. {
  1159.    struct filter_list *new ;
  1160.    
  1161.    if ((new = (struct filter_list *)calloc(1,sizeof(struct filter_list))) != NULL)
  1162.       {
  1163.       new->next = list ;
  1164.       new->str = strupr(strdup(str)) ;
  1165.       if (new->str == NULL)
  1166.      new = NULL ;
  1167.       }
  1168.    if (new == NULL)
  1169.       {
  1170.       fputs("Error: out of memory\n",stderr) ;
  1171.       exit(1) ;
  1172.       }
  1173.    return new ;
  1174. }
  1175.  
  1176. /***********************************************/
  1177.  
  1178. void build_filter_lists(file)
  1179. char *file ;
  1180. {
  1181.    FILE *fp ;
  1182.    char buf[MAXLINE] ;
  1183.    int len ;
  1184.    
  1185.    if ((fp = fopen(file,"r")) == NULL)
  1186.       {
  1187.       fputs("Warning: unable to open filtering file, will print entire list.\n",stderr) ;
  1188.       do_filter = FALSE ;
  1189.       }
  1190.    else /* OK, file is open, so start reading */
  1191.       {
  1192.       while (!feof(fp))
  1193.      {
  1194.      buf[0] = '\0' ;
  1195.      if (fgets(buf, sizeof(buf), fp) == NULL)
  1196.         {
  1197.         if (!feof(fp)) /* was it an error other than EOF? */
  1198.            fputs("Warning: error reading filtering data, filtering may be incomplete.\n",stderr) ;
  1199.         break ;
  1200.         }
  1201.      len = strlen(buf) ;
  1202.      if (len > 0 && buf[len-1] == '\n')
  1203.         buf[--len] = '\0' ;
  1204.      if (len > 1)
  1205.         {
  1206.         switch (buf[0])
  1207.            {
  1208.            case '+':
  1209.           includes = add_filter_info(includes,buf+1) ;
  1210.           break ;
  1211.            case '-':
  1212.           excludes = add_filter_info(excludes,buf+1) ;
  1213.           break ;
  1214.            case '#':        /* comment lines */
  1215.            default:
  1216.           break ;
  1217.            }
  1218.         }
  1219.      }
  1220.       fclose(fp) ;
  1221.       do_filter = TRUE ;
  1222.       }
  1223. }
  1224.  
  1225. /***********************************************/
  1226.  
  1227. int _Cdecl main(argc,argv)
  1228. int argc ;
  1229. char *argv[] ;
  1230. {
  1231.    int lines_per_page = -1 ;
  1232.    int total_lines = -1 ;
  1233.    int use_FF = TRUE ;
  1234.    int last_line ;
  1235.    int body_lines ;
  1236.    char *typeface = NULL ;
  1237.    char *summary_file = NULL ;
  1238.    char *formats_file = NULL ;
  1239.    char *filter_file = NULL ;
  1240.    char *last_page_num ;
  1241.    
  1242.    fputs("INTPRINT v", stderr) ;
  1243.    fputs(VERSION, stderr) ;
  1244.    fputs(" by Ralf Brown and others.  Donated to the Public Domain.\n",stderr) ;
  1245.    if (argc == 1 && isatty(0))
  1246.       usage() ;      /* give help if invoked with no args and keybd input */
  1247.    while (argc >= 2 && argv[1][0] == '-')
  1248.       {
  1249.       switch (argv[1][1])
  1250.      {
  1251.      case 'B':
  1252.         printer_bold = TRUE ;
  1253.         /* fall through to -b */
  1254.      case 'b':
  1255.         boldface = TRUE ;
  1256.         break ;
  1257.      case 'd':
  1258.         duplex = TRUE ;
  1259.         break ;
  1260.      case 'e':
  1261.         indent = 8 ;
  1262.         page_width = 87 ;  /* 96 - indent - 1 right margin */
  1263.         break ;
  1264.      case 'f':
  1265.         formats_file = argv[1]+2 ;
  1266.         break ;
  1267.      case 'F':
  1268.         filter_file = argv[1]+2 ;
  1269.         break ;
  1270.      case 'H':   /* page headers */
  1271.         do_headers = TRUE ;
  1272.         break ;
  1273.      case 'i':
  1274.         indent = atoi(argv[1]+2) ;
  1275.         break ;
  1276.      case 'I':
  1277.         IBM_chars = TRUE ;
  1278.         break ;
  1279.      case 'l':
  1280.         lines_per_page = atoi(argv[1]+2) ;
  1281.         break ;
  1282.      case 'L':
  1283.         total_lines = atoi(argv[1]+2) ;
  1284.         break ;
  1285.      case 'm':
  1286.         multi_file = TRUE ;
  1287.         break ;
  1288.      case 'n':
  1289.         pages_printed = atoi(argv[1]+2) ;
  1290.         break ;
  1291.      case 'P':
  1292.         if (argv[1][2] == '?')
  1293.            display_printers() ;
  1294.         else
  1295.            select_printer(argv[1]+2) ;
  1296.         break ;
  1297.      case 'p':
  1298.         page_numbers = TRUE ;
  1299.         break ;
  1300.      case 'r':
  1301.         first_page = atoi(argv[1]+2) ;
  1302.         last_page_num = strchr(argv[1]+2, ':') ;
  1303.         last_page = last_page_num ? atoi(last_page_num+1) : 0 ;
  1304.         if (last_page == 0)
  1305.            last_page = 9999 ;
  1306.         break ;
  1307.      case 's':
  1308.         summary_file = argv[1]+2 ;
  1309.         break ;
  1310.      case 't':
  1311.         typeface = argv[1]+2 ;
  1312.         break ;
  1313.      case 'w':
  1314.         widow_length = atoi(argv[1]+2) ;
  1315.         break ;
  1316.      default:
  1317.         usage() ;
  1318.      }
  1319.       argv++ ;
  1320.       argc-- ;
  1321.       }
  1322.    if (printer == NULL)
  1323.       select_printer("default") ;
  1324.    /* apply any necessary overrides to parameters */
  1325.    if (printer->indent != -1)
  1326.       indent = printer->indent ;
  1327.    if (lines_per_page <= 0)
  1328.       lines_per_page = printer->lines_per_page ;
  1329.    if (total_lines <= 0)
  1330.       total_lines = printer->page_length ;
  1331.    if (page_width <= 0)
  1332.       page_width = printer->page_width ;
  1333.    if (printer->flag)
  1334.       *(printer->flag) = TRUE ;
  1335.    if (cstrlen(&printer->bold_on) == 0)     /* control sequences for bold? */
  1336.       printer_bold = FALSE ;        /* if not, don't try to use them */
  1337.  
  1338.    /* open the summary file, if any */
  1339.    if (summary_file && *summary_file)
  1340.       if ((summary = fopen(summary_file, pages_printed ? "a":"w")) != NULL)
  1341.      do_summary = TRUE ;
  1342.       else
  1343.      fputs("unable to open summary file\n", stderr) ;
  1344.    /* open the data formats file, if any */
  1345.    if (formats_file && *formats_file)
  1346.       if ((formats = fopen(formats_file, pages_printed ? "a":"w")) != NULL)
  1347.      do_formats = TRUE ;
  1348.       else
  1349.      fputs("unable to open formats file\n", stderr) ;
  1350.    /* initialize filtering data, if specified */
  1351.    if (filter_file && *filter_file)
  1352.       build_filter_lists(filter_file) ;
  1353.    if (total_lines <= lines_per_page)
  1354.       {
  1355.       total_lines = lines_per_page ;
  1356.       use_FF = TRUE ;
  1357.       }
  1358.    else
  1359.       use_FF = FALSE ;
  1360.    if (argc == 2 || argc == 3)
  1361.       {
  1362.       input_file = argv[1] ;
  1363.       infile = fopen(input_file,"r") ;
  1364.       if (infile == NULL)
  1365.      fatal("unable to open input file") ;
  1366.       if (argc == 3)
  1367.      {
  1368.      outfile = fopen(argv[2],(pages_printed?"a":"w")) ;
  1369.      if (outfile == NULL)
  1370.         fatal("unable to open output file") ;
  1371.      }
  1372.       else
  1373.      outfile = stdout ;
  1374.       }
  1375.    else
  1376.       usage() ;
  1377.    if (lines_per_page < 20 || lines_per_page > MAXPAGE)
  1378.       {
  1379.       fputs("Surely you jest!  At least 20 and at most 200 lines per page.\n\n", stderr) ;
  1380.       usage() ;
  1381.       }
  1382.    if (widow_length < 3 || widow_length > lines_per_page / 2)
  1383.       {
  1384.       fputs("Widow lines (-w) must be set to at least 3 and at most one-half of the\n",stderr) ;
  1385.       fputs("page length.  Using default of 10 lines.\n",stderr) ;
  1386.       widow_length = 10 ;
  1387.       }
  1388. #ifdef __TURBOC__
  1389.    setvbuf(infile,NULL,_IOFBF,10240) ;    /* use larger disk buffers */
  1390.    setvbuf(outfile,NULL,_IOFBF,10240) ; /* for better performance */
  1391.    if (do_summary)
  1392.       setvbuf(summary,NULL,_IOFBF,4096) ;
  1393.    if (do_formats)
  1394.       setvbuf(formats,NULL,_IOFBF,4096) ;
  1395. #endif /* __TURBOC__ */
  1396.    /* set up the printer */
  1397.    fputcstr(&printer->init1,outfile) ;
  1398.    fputcstr(&printer->init2,outfile) ;
  1399.    if (printer->set_typeface)
  1400.       (*printer->set_typeface)(outfile,typeface) ;
  1401.    if (duplex)
  1402.       {
  1403.       fputcstr(&printer->duplex_on,outfile) ;
  1404.       if ((pages_printed % 2) == 1)    /* next page odd or even? */
  1405.      fputcstr(&printer->marginl,outfile) ;    /* even */
  1406.       else
  1407.      fputcstr(&printer->marginr,outfile) ;    /* odd */
  1408.       }
  1409.    else
  1410.       fputcstr(&printer->marginc,outfile) ;    /* non-duplex, so center */
  1411.    /* start the summary file */
  1412.    if (do_summary && pages_printed == 0)
  1413.       {          /* create header, but only on first part */
  1414.       /* set up the printer */
  1415.       fputcstr(&printer->init1,summary) ;
  1416.       fputcstr(&printer->init2,summary) ;
  1417.       fputcstr(&printer->marginc,summary) ;
  1418.       indent_line(summary) ;
  1419.       fputs("\t\t\t\tInterrupt Summary\n",summary) ;
  1420.       indent_line(summary) ;
  1421.       fputs("\t\t\t\t", summary) ;
  1422.       (*printer->put_line)(summary,17) ;
  1423.       fputs("\n\n",summary) ;
  1424.       indent_line(summary) ;
  1425.       fputs("INT AH AL", summary) ;
  1426.       if (page_numbers)
  1427.      fputs(" Page", summary) ;
  1428.       fputs("\t\t\tDescription\n", summary) ;
  1429.       indent_line(summary) ;
  1430.       (*printer->put_line)(summary,page_width) ;
  1431.       fputc('\n', summary) ;
  1432.       }
  1433.    /* start the data formats file */
  1434.    if (do_formats && pages_printed == 0)
  1435.       {          /* create header, but only on first part */
  1436.       /* set up the printer */
  1437.       fputcstr(&printer->init1,formats) ;
  1438.       fputcstr(&printer->init2,formats) ;
  1439.       fputcstr(&printer->marginc,formats) ;
  1440.       indent_line(formats) ;
  1441.       fputs("\t\t\tData Structure Formats\n", formats) ;
  1442.       indent_line(formats) ;
  1443.       fputs("\t\t\t", formats) ;
  1444.       (*printer->put_line)(formats,22) ;
  1445.       fputs("\n\n", formats) ;
  1446.       indent_line(formats) ;
  1447.       fputs("INT AH AL", formats) ;
  1448.       if (page_numbers)
  1449.      fputs(" Page", formats) ;
  1450.       fputs("\t\tData Structure\n", formats) ;
  1451.       }
  1452.    if (page_numbers)
  1453.       body_lines = lines_per_page - 2 ;
  1454.    else
  1455.       body_lines = lines_per_page ;
  1456.    if (do_headers)
  1457.       body_lines -= 2 ;
  1458.    last_line = 0 ;
  1459.    while (!feof(infile) && !out_of_files)
  1460.       {
  1461.       fill_buffer(last_line,body_lines) ;
  1462.       last_line = find_page_break(body_lines) ;
  1463.       print_buffer(last_line,lines_per_page,total_lines,use_FF) ;
  1464.       }
  1465.    if (last_line < body_lines)
  1466.       {
  1467.       int i ;
  1468.       
  1469.       for (i = last_line ; i < body_lines ; i++)
  1470.      strcpy(buffer[i-last_line], buffer[i]) ;
  1471.       print_buffer(body_lines-last_line,lines_per_page,total_lines,use_FF) ;
  1472.       }
  1473.    /* reset the printer */
  1474.    fputcstr(&printer->term1,outfile) ;
  1475.    fputcstr(&printer->term2,outfile) ;
  1476.    fflush(outfile) ;
  1477.    itoa(pages_printed, num, 10) ;
  1478.    fputs(num, stderr) ;
  1479.    fputs(" pages\n", stderr) ;
  1480.    if (do_summary)
  1481.       {
  1482.       /* reset the printer */
  1483.       fputcstr(&printer->term1,summary) ;
  1484.       fputcstr(&printer->term2,summary) ;
  1485.       fclose(summary) ;
  1486.       }
  1487.    if (do_formats)
  1488.       {
  1489.       /* reset the printer */
  1490.       fputcstr(&printer->term1,formats) ;
  1491.       fputcstr(&printer->term2,formats) ;
  1492.       fclose(formats) ;
  1493.       }
  1494.    fclose(infile) ;
  1495.    return 0 ;
  1496. }
  1497.